/*
*  Copyright 2019-2023 Zheng Jie
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*  http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/
package me.zhengjie.modules.system.service.impl;

import me.zhengjie.modules.system.domain.*;
import me.zhengjie.modules.system.domain.vo.QuestionQueryCriteria;
import me.zhengjie.modules.system.mapper.QuestionMapper;
import me.zhengjie.modules.system.mapper.QuestiontypeMapper;
import me.zhengjie.modules.system.mapper.UserMapper;
import me.zhengjie.modules.system.service.ExercisesetandquestionService;
import me.zhengjie.modules.system.service.QuestiontypeService;
import me.zhengjie.utils.FileUtil;
import lombok.RequiredArgsConstructor;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import me.zhengjie.modules.system.service.ExercisesetService;
import me.zhengjie.modules.system.domain.vo.ExercisesetQueryCriteria;
import me.zhengjie.modules.system.mapper.ExercisesetMapper;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import me.zhengjie.utils.PageUtil;

import java.util.*;
import java.io.IOException;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.servlet.http.HttpServletResponse;

import me.zhengjie.utils.PageResult;

/**
* @description 服务实现
* @author shitou
* @date 2024-04-21
**/
@Service
@RequiredArgsConstructor
public class ExercisesetServiceImpl extends ServiceImpl<ExercisesetMapper, Exerciseset> implements ExercisesetService {

    private final ExercisesetMapper exercisesetMapper;

    private final UserMapper userMapper;

    private final QuestionMapper questionMapper;

    private final ExercisesetandquestionService exercisesetandquestionsService;

    @Override
    public PageResult<Exerciseset> queryAll(ExercisesetQueryCriteria criteria, Page<Object> page){

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String currentUserName = authentication.getName();
        User currentUser = userMapper.findByUsername(currentUserName);

        criteria.setSchoolId(currentUser.getDeptId());
        criteria.setUserId(Math.toIntExact(currentUser.getId()));
        return PageUtil.toPage(exercisesetMapper.findAll(criteria, page));
    }

    @Override
    public List<Exerciseset> queryAll(ExercisesetQueryCriteria criteria){
        return exercisesetMapper.findAll(criteria);
    }

    public  List<Exerciseset> queryAllLikeName(ExercisesetQueryCriteria criteria){
        return exercisesetMapper.queryAllLikeName(criteria);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(Exerciseset resources) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String currentUserName = authentication.getName();
        User currentUser = userMapper.findByUsername(currentUserName);

        resources.setSchoolId(currentUser.getDeptId());
        resources.setUserId(currentUser.getId());
        save(resources);
    }
    public QuestionNum getQuestionNum(QuicklyQuestion criteria){
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String currentUserName = authentication.getName();
        User currentUser = userMapper.findByUsername(currentUserName);
        criteria.setIsPublish(1);
        criteria.setIsShare(1);
        criteria.setSchoolId(currentUser.getDeptId());
        List<Question> questionList = questionMapper.findAll2(criteria);
        QuestionNum questionNum = new QuestionNum();
        for(Question item: questionList){
            if(item.getType() == 0){
                if(questionNum.getSingleNum()==null){
                    questionNum.setSingleNum(0);
                }
                questionNum.setSingleNum(1 + Integer.valueOf(questionNum.getSingleNum()));
            } else if(item.getType() == 1){
                if(questionNum.getMultipleNum()==null){
                    questionNum.setMultipleNum(0);
                }
                questionNum.setMultipleNum(1+ Integer.valueOf(questionNum.getMultipleNum()));
            } else if(item.getType() == 2){
                if(questionNum.getJudgeNum()==null){
                    questionNum.setJudgeNum(0);
                }
                questionNum.setJudgeNum(1+ Integer.valueOf(questionNum.getJudgeNum()));
            } else if(item.getType() == 3){
                if(questionNum.getCompletionNum()==null){
                    questionNum.setCompletionNum(0);
                }
                questionNum.setCompletionNum(1+ Integer.valueOf(questionNum.getCompletionNum()));
            } else if(item.getType() == 4){
                if(questionNum.getShortNum()==null){
                    questionNum.setShortNum(0);
                }
                questionNum.setShortNum(1+ Integer.valueOf(questionNum.getShortNum()));
            }
        }
        return questionNum;
    }

    public Integer queryQuicklyQuestion(QuicklyQuestion criteria){

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String currentUserName = authentication.getName();
        User currentUser = userMapper.findByUsername(currentUserName);


//        criteria.setIsShare(1);
        criteria.setIsPublish(1);
        criteria.setSchoolId(currentUser.getDeptId());
        if(criteria.getDifficulty().size()==0){
            criteria.setDifficulty(null);
        }
        if(criteria.getQuestionTypeArr().size()==0){
            criteria.setQuestionTypeArr(null);
        }
        List<Question> questionList = questionMapper.findAll2(criteria);

        //单选
        List<Question> singleList = new ArrayList<>();
        //多选
        List<Question> multipleList = new ArrayList<>();
        //判断
        List<Question> judgList = new ArrayList<>();
        //填空
        List<Question> completionList = new ArrayList<>();
        //简答
        List<Question> shortList = new ArrayList<>();
        for(Question item: questionList){
            if(item.getType() == 0){
                singleList.add(item);
            } else if(item.getType() == 1){
                multipleList.add(item);
            } else if(item.getType() == 2){
                judgList.add(item);
            } else if(item.getType() == 3){
                completionList.add(item);
            } else if(item.getType() == 4){
                shortList.add(item);
            }
        }
        //单选
        List<Integer> singleList2 = new ArrayList<>();

        //多选
        List<Integer> multipleList2 = new ArrayList<>();
        //判断
        List<Integer> judgList2 = new ArrayList<>();
        //填空
        List<Integer> completionList2 = new ArrayList<>();
        //简答
        List<Integer> shortList2 = new ArrayList<>();
        if((singleList.size()>criteria.getSingleNum() || singleList.size()==criteria.getSingleNum()) && criteria.getSingleNum()!=0){
            //单选
            singleList2 = getRandomElements(singleList,criteria.getSingleNum());
        } else if(singleList.size()<criteria.getSingleNum()){
            return -1;
        }

        if((multipleList.size() >criteria.getMultipleNum() || multipleList.size() ==criteria.getMultipleNum()) && criteria.getMultipleNum()!=0){
            multipleList2 = getRandomElements(multipleList,criteria.getMultipleNum());
        } else if(multipleList.size() <criteria.getMultipleNum()){
            return -2;
        }

        if((judgList.size() >criteria.getJudgeNum() || judgList.size() == criteria.getJudgeNum()) && criteria.getJudgeNum()!=0){
            judgList2 = getRandomElements(judgList,criteria.getJudgeNum());
        } else if(judgList.size() <criteria.getJudgeNum()){
            return -3;
        }

        if((completionList.size() >criteria.getCompletionNum() || completionList.size() ==criteria.getCompletionNum()) && criteria.getCompletionNum()!=0){
            completionList2 = getRandomElements(judgList,criteria.getCompletionNum());
        } else if(completionList.size() <criteria.getCompletionNum()){
            return -4;
        }
        if((shortList.size() > criteria.getShortNum() || shortList.size() == criteria.getShortNum()) && criteria.getShortNum()!=0){
            shortList2 = getRandomElements(judgList,criteria.getShortNum());
        } else if(shortList.size() <criteria.getShortNum()){
            return -5;
        }

        List<List<Integer>> listsToMerge = new ArrayList<>();
        listsToMerge.add(singleList2);
        listsToMerge.add(multipleList2);
        listsToMerge.add(judgList2);
        listsToMerge.add(completionList2);
        listsToMerge.add(shortList2);

        List<Integer> mergedList = listsToMerge.stream()
                .flatMap(List::stream)
                .collect(Collectors.toList());

        Exerciseset exerciseset = new Exerciseset();


        exerciseset.setName(criteria.getName());
        exerciseset.setState(1);
        exerciseset.setType("0");
        exerciseset.setSchoolId(currentUser.getDeptId());
        exerciseset.setUserId(currentUser.getId());
        save(exerciseset);

        for(Integer item: mergedList){
            Exercisesetandquestion exercisesetandquestion = new Exercisesetandquestion();
            exercisesetandquestion.setQuestionid(item);
            exercisesetandquestion.setExercisesetid(exerciseset.getId());
            exercisesetandquestionsService.save(exercisesetandquestion);
        }


        return 1;
    }

    //随机抽取
    private static List<Integer> getRandomElements(List<Question> list, int numberOfElements) {


        List<Integer> result = new ArrayList<>();
        Set<Integer> pickedIndices = new HashSet<>();
        Random rand = new Random();

        while (result.size() <numberOfElements ){
            int index = rand.nextInt(list.size());
            if (!pickedIndices.contains(index)) {
                result.add(list.get(index).getId());
                pickedIndices.add(index);
            }
        }

        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(Exerciseset resources) {
        Exerciseset exerciseset = getById(resources.getId());
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String currentUserName = authentication.getName();
        User currentUser = userMapper.findByUsername(currentUserName);

        resources.setSchoolId(currentUser.getDeptId());
        resources.setUserId(currentUser.getId());
        exerciseset.copy(resources);
        saveOrUpdate(exerciseset);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteAll(List<Integer> ids) {
        removeBatchByIds(ids);
    }

    @Override
    public void download(List<Exerciseset> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (Exerciseset exerciseset : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put(" name",  exerciseset.getName());
            map.put(" type",  exerciseset.getType());
            map.put(" lastupdatetime",  exerciseset.getLastupdatetime());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }
}